package io.adrainty.bolee.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.adrainty.bolee.framework.commons.basic.ResponseCode;
import io.adrainty.bolee.framework.commons.basic.TreeDTO;
import io.adrainty.bolee.framework.commons.basic.TreeItemDTO;
import io.adrainty.bolee.framework.commons.exception.AppException;
import io.adrainty.bolee.framework.commons.utils.IdentifierNoUtil;
import io.adrainty.bolee.framework.commons.utils.TreeItemUtil;
import io.adrainty.bolee.insurance.models.entity.*;
import io.adrainty.bolee.insurance.repository.ICategoryRepository;
import io.adrainty.bolee.insurance.repository.IConditionRepository;
import io.adrainty.bolee.insurance.service.ICategoryService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>CategoryServiceImpl</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description 筛选项管理
 * @since 2025/8/11 11:20:49
 */

@Service
public class CategoryServiceImpl implements ICategoryService {

    @Resource
    private ICategoryRepository categoryRepository;

    @Resource
    private IConditionRepository conditionRepository;

    @Override
    public IPage<CategoryEntity> findCategoryPage(Integer pageNum, Integer pageSize, CategoryEntity searchDTO) {
        IPage<CategoryEntity> pageResult = categoryRepository.findCategoryPage(pageNum, pageSize, searchDTO);
        if (CollUtil.isNotEmpty(pageResult.getRecords())) {
            List<CategoryEntity> records = pageResult.getRecords();
            fillCategoryData(records);
        }
        return pageResult;
    }

    @Override
    public List<CategoryEntity> findCategoryList(CategoryEntity searchDTO) {
        List<CategoryEntity> categoryList = categoryRepository.findCategoryList(searchDTO);
        fillCategoryData(categoryList);
        return categoryList;
    }

    @Override
    public CategoryEntity createCategory(CategoryEntity entity) {
        if (StringUtils.isBlank(entity.getParentCategoryNo())) {
            entity.setParentCategoryNo(IdentifierNoUtil.ROOT_PARENT_ID);
        }

        String currentCategoryNo = createCategoryNo(entity.getParentCategoryNo());
        entity.setCategoryNo(currentCategoryNo);
        if (!categoryRepository.createCategory(entity)) {
            throw new AppException(ResponseCode.CONDITION_CREATE_ERROR);
        }
        return entity;
    }

    @Override
    @Transactional
    public Boolean updateCategory(CategoryEntity entity) {
        if (entity.getId() == null) {
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER);
        }

        if (!categoryRepository.updateCategory(entity)) {
            throw new AppException(ResponseCode.CATEGORY_UPDATE_ERROR);
        }

        // 保存分类筛选项
        if (CollUtil.isNotEmpty(entity.getCategoryConditionVOs())) {
            List<CategoryConditionEntity> conditionVOs = entity.getCategoryConditionVOs();
            conditionVOs.forEach(conditionVO -> conditionVO.setCategoryNo(entity.getCategoryNo()));
            categoryRepository.deleteCategoryConditionByCategoryNo(List.of(entity.getCategoryNo()));
            categoryRepository.saveBatchCategoryCondition(conditionVOs);
        }

        // 保存分类系数项
        if (CollUtil.isNotEmpty(entity.getCategoryCoefficentVOs())) {
            List<CategoryCoefficientEntity> coefficientVOs = entity.getCategoryCoefficentVOs();
            coefficientVOs.forEach(coefficientVO -> coefficientVO.setCategoryNo(entity.getCategoryNo()));
            categoryRepository.deleteCategoryCoefficientByCategoryNo(List.of(entity.getCategoryNo()));
            categoryRepository.saveBatchCategoryCoefficient(coefficientVOs);
        }

        // 保存分类保障项
        if (CollUtil.isNotEmpty(entity.getCategorySafeguardVOs())) {
            List<CategorySafeguardEntity> safeguardVOs = entity.getCategorySafeguardVOs();
            safeguardVOs.forEach(safeguardVO -> safeguardVO.setCategoryNo(entity.getCategoryNo()));
            categoryRepository.deleteCategorySafeguardByCategoryNo(List.of(entity.getCategoryNo()));
            categoryRepository.saveBatchCategorySafeguard(safeguardVOs);
        }

        return true;
    }

    @Override
    @Transactional
    public Boolean deleteCategory(List<String> deleteIdList) {
        List<CategoryEntity> categoryEntities = categoryRepository.listCategoryList(deleteIdList);
        if (CollUtil.isEmpty(categoryEntities)) return Boolean.TRUE;
        List<String> categoryNoList = categoryEntities.stream().map(CategoryEntity::getCategoryNo).toList();
        categoryRepository.deleteCategoryConditionByCategoryNo(categoryNoList);
        categoryRepository.deleteCategoryCoefficientByCategoryNo(categoryNoList);
        categoryRepository.deleteCategorySafeguardByCategoryNo(categoryNoList);
        return categoryRepository.deleteCategory(deleteIdList);
    }

    @Override
    public List<CategoryConditionEntity> findCategoryConditionList(CategoryConditionEntity entity) {
        List<CategoryConditionEntity> conditionEntities = categoryRepository.findCategoryConditionList(entity);
        List<String> conditionKeys = conditionEntities.stream().map(CategoryConditionEntity::getConditionKey).toList();
        ConditionEntity conditionDTO = ConditionEntity.builder()
                .conditionKeys(conditionKeys.toArray(new String[0]))
                .build();
        Map<String, ConditionEntity> conditionMap = conditionRepository.findConditionList(conditionDTO).stream()
                .collect(Collectors.toMap(ConditionEntity::getConditionKey, v -> v));
        for (CategoryConditionEntity condition : conditionEntities) {
            if (conditionMap.containsKey(condition.getConditionKey())) {
                condition.setConditionVal(conditionMap.get(condition.getConditionKey()).getConditionVal());
            }
        }
        return conditionEntities;
    }

    @Override
    public TreeDTO categoryTree(CategoryEntity entity) {
        String parentCategoryNo = StringUtils.defaultIfBlank(entity.getParentCategoryNo(), IdentifierNoUtil.ROOT_PARENT_ID);
        List<CategoryEntity> categoryEntities = categoryRepository.findSubCategoryList(
                entity.getCategoryType(), parentCategoryNo);
        if (CollUtil.isEmpty(categoryEntities)) {
            throw new AppException(ResponseCode.CATEGORY_NOT_EXIST);
        }

        List<String> checkedIds = entity.getCheckedCategoryNos() == null? List.of() :
                Arrays.stream(entity.getCheckedCategoryNos()).toList();
        List<String> expandedIds = new ArrayList<>();
        // 下面Contains要用 转为Set加快效率
        Set<String> checkedIdSet = new HashSet<>(checkedIds);
        List<TreeItemDTO> treeItemDTOList = categoryEntities.stream().map(category -> {
            TreeItemDTO treeItemDTO = TreeItemDTO.builder()
                    .id(category.getCategoryNo())
                    .parentId(category.getParentCategoryNo())
                    .label(category.getCategoryName())
                    .isChecked(checkedIdSet.contains(category.getCategoryNo()))
                    .build();
            // 展开项, 默认展开为二级
            // 如果为100_001_001_000_000 > 100_001_001 才展开
            // 如果为100_001_001_001_000 > 100_001_001_001 就不展开
            if (IdentifierNoUtil.processNo(category.getCategoryNo()).length() / 3 == 3) {
                expandedIds.add(category.getCategoryNo());
            }
            return treeItemDTO;
        }).toList();

        return TreeItemUtil.returnTreeDTO(checkedIds, expandedIds, parentCategoryNo, treeItemDTOList);
    }

    private String createCategoryNo(String parentCategoryNo) {
        List<CategoryEntity> categoryEntities = categoryRepository.findSub1LevelCategoryList(parentCategoryNo);
        if (CollUtil.isEmpty(categoryEntities)) {
            return IdentifierNoUtil.createNo(parentCategoryNo, false);
        } else {
            return categoryEntities.stream()
                    .map(dept -> Long.valueOf(dept.getCategoryNo()))
                    .max(Comparator.comparing(i -> i))
                    .map(String::valueOf)
                    .map(i -> IdentifierNoUtil.createNo(i, true))
                    .orElse(IdentifierNoUtil.createNo(parentCategoryNo, false));
        }
    }

    /**
     * 填充分类数据
     * @param records 分类列表
     */
    private void fillCategoryData(List<CategoryEntity> records) {
        Set<String> categoryNoSet = records.stream().map(CategoryEntity::getCategoryNo).collect(Collectors.toSet());
        Map<String, List<CategoryConditionEntity>> categoryConditionMap = categoryRepository.findCategoryConditionByCategoryNo(categoryNoSet)
                .stream()
                .collect(Collectors.groupingBy(CategoryConditionEntity::getCategoryNo));
        Map<String, List<CategorySafeguardEntity>> categorySafeguardMap = categoryRepository.findCategorySafeguardByCategoryNo(categoryNoSet)
                .stream()
                .collect(Collectors.groupingBy(CategorySafeguardEntity::getCategoryNo));
        Map<String, List<CategoryCoefficientEntity>> categoryCoefficientMap = categoryRepository.findCategoryCoefficientByCategoryNo(categoryNoSet)
                .stream()
                .collect(Collectors.groupingBy(CategoryCoefficientEntity::getCategoryNo));

        for (CategoryEntity entity : records) {
            entity.setCategoryConditionVOs(categoryConditionMap.getOrDefault(entity.getCategoryNo(), new ArrayList<>()));
            entity.setCategorySafeguardVOs(categorySafeguardMap.getOrDefault(entity.getCategoryNo(), new ArrayList<>()));
            entity.setCategoryCoefficentVOs(categoryCoefficientMap.getOrDefault(entity.getCategoryNo(), new ArrayList<>()));
        }
    }
    
}
